]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
keyboard: Plug a leak of KeyboardControllers
authorJonas Dreßler <verdre@v0yd.nl>
Tue, 18 Feb 2020 14:05:57 +0000 (15:05 +0100)
committerFlorian Müllner <florian.muellner@gmail.com>
Tue, 18 Feb 2020 14:48:39 +0000 (14:48 +0000)
To make sure the GC really disposes the KeyboardController object we
need to remove all references to the object, which means we have to
disconnect signals the object connects to, too.

This also fixes a bug where keys remain pressed forever and thus also
break that key on real keyboards. It happens if the OSK gets destroyed
during an OSK-key is being held so the StButton of the key is not
released. That means the key remains pressed in the
MetaVirtualInputDevice that we are now leaking because
KeyboardController isn't garbage collected.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/1015

js/ui/keyboard.js

index 868a4b3d3643a082d2238589a5bf1eedad75e70d..15d92c5924211548c3049c1ba16f8dc1fb5b1a82 100644 (file)
@@ -1255,11 +1255,7 @@ class Keyboard extends St.BoxLayout {
 
         this._clearShowIdle();
 
-        this._keyboardController = null;
-        this._suggestions = null;
-        this._aspectContainer = null;
-        this._emojiSelection = null;
-        this._keypad = null;
+        this._keyboardController.destroy();
 
         Main.layoutManager.untrackChrome(this);
         Main.layoutManager.keyboardBox.remove_actor(this);
@@ -1844,13 +1840,20 @@ var KeyboardController = class {
                                                                    this._onSourcesModified.bind(this));
         this._currentSource = this._inputSourceManager.currentSource;
 
-        Main.inputMethod.connect('notify::content-purpose',
-                                 this._onContentPurposeHintsChanged.bind(this));
-        Main.inputMethod.connect('notify::content-hints',
-                                 this._onContentPurposeHintsChanged.bind(this));
-        Main.inputMethod.connect('input-panel-state', (o, state) => {
-            this.emit('panel-state', state);
-        });
+        this._notifyContentPurposeId = Main.inputMethod.connect(
+            'notify::content-purpose', this._onContentPurposeHintsChanged.bind(this));
+        this._notifyContentHintsId = Main.inputMethod.connect(
+            'notify::content-hints', this._onContentPurposeHintsChanged.bind(this));
+        this._notifyInputPanelStateId = Main.inputMethod.connect(
+            'input-panel-state', (o, state) => this.emit('panel-state', state));
+    }
+
+    destroy() {
+        this._inputSourceManager.disconnect(this._sourceChangedId);
+        this._inputSourceManager.disconnect(this._sourcesModifiedId);
+        Main.inputMethod.disconnect(this._notifyContentPurposeId);
+        Main.inputMethod.disconnect(this._notifyContentHintsId);
+        Main.inputMethod.disconnect(this._notifyInputPanelStateId);
     }
 
     _onSourcesModified() {